package com.itheima.wms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.pinda.exception.BizException;
import com.itheima.wms.common.enums.LocationFrozen;
import com.itheima.wms.common.enums.LocationUseStatus;
import com.itheima.wms.common.enums.StockStatus;
import com.itheima.wms.common.service.CrudServiceImpl;
import com.itheima.wms.dao.GoodsMapper;
import com.itheima.wms.dao.LocationMapper;
import com.itheima.wms.dao.StockMapper;
import com.itheima.wms.entity.GoodsEntity;
import com.itheima.wms.entity.LocationEntity;
import com.itheima.wms.entity.StockEntity;
import com.itheima.wms.service.StockService;
import com.itheima.wms.vo.StockDetailVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;


/**
 * <p>
 * 业务实现类
 * 库存
 * </p>
 */
@Slf4j
@Service
public class StockServiceImpl extends CrudServiceImpl<StockMapper, StockEntity> implements StockService {

    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private LocationMapper locationMapper;

    @Override
    public IPage<StockDetailVO> pageDetail(Page<StockDetailVO> page, Map data) {
        IPage<StockDetailVO> iPage = this.baseMapper.selectStockDetail(page, data);
        return iPage;
    }

    @Override
    public List<StockDetailVO> listDetail(Map data) {
        return this.baseMapper.selectStockDetail(data);
    }

    @Override
    public StockEntity getOneByLocationId(Long id) {
        LambdaQueryWrapper<StockEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StockEntity::getLocationId, id);
        return this.baseMapper.selectOne(wrapper);
    }

    @Override
    public boolean frozen(Long stockId, Integer num) {
        if (num == null || num == 0) {
            throw new BizException("冻结数量为空");
        }
        StockEntity stockEntity = this.baseMapper.selectById(stockId);
        log.info("冻结库存:{}; {}", num, stockEntity);
        if (stockEntity == null || num > stockEntity.getFree()) {
            throw new BizException("可用库存不足,无法冻结库存");
        }
        stockEntity.setFrozen(num + stockEntity.getFrozen());
        stockEntity.setFree(stockEntity.getTotal() - stockEntity.getFrozen());
        return this.baseMapper.updateById(stockEntity) > 0;
    }

    @Override
    public boolean unfreeze(Long stockId, Integer num) {
        if (num == null || num == 0) {
            throw new BizException("解冻数量为空");
        }
        StockEntity stockEntity = this.baseMapper.selectById(stockId);
        log.info("解冻库存:{}; {}", num, stockEntity);
        if (stockEntity == null || num > stockEntity.getFrozen()) {
            throw new BizException("冻结库存不足,无法解冻库存");
        }
        stockEntity.setFrozen(stockEntity.getFrozen() - num);
        stockEntity.setFree(stockEntity.getTotal() - stockEntity.getFrozen());
        return this.baseMapper.updateById(stockEntity) > 0;
    }

    @Override
    public boolean saveOrUpdate(StockEntity entity) {
        StockEntity dbEntity = this.getById(entity.getId());
        // 计算是否已满
        GoodsEntity goodsEntity = goodsMapper.selectById(entity.getGoodsId());
        LocationEntity locationEntity = locationMapper.selectById(entity.getLocationId());
        log.info(" >>>数据库库存：{} \n >>>传入库存:{} \n >>>货品:{} \n >>>库位:{}", dbEntity, entity, goodsEntity, locationEntity);

        if (entity.getTotal() > 0) {
            entity.setStatus(StockStatus.UNFULL.getCode()); // 未满
            locationEntity.setUseStatus(LocationUseStatus.UNFULL.getCode()); // 库存已占用

            // 最大承载个数
            Integer maxNum = locationEntity.getMaxVolume().divide(goodsEntity.getVolume(), 2, BigDecimal.ROUND_HALF_UP).intValue();
            // 已存在库存个数
            Integer dbTotal = (dbEntity != null && dbEntity.getTotal() > 0) ? dbEntity.getTotal() : 0;
            // 将要变更的库存个数
            Integer total = entity.getTotal();

            log.info("库存变更信息 maxNum:{} dbTotal:{} total:{}", maxNum, dbEntity, total);

            if (total > maxNum) {
                throw new BizException(locationEntity.getName() + " 库位最多还可承载 " + (maxNum - dbTotal) + " 个 " + goodsEntity.getName());
            }

            if (maxNum == total) {
                entity.setStatus(StockStatus.FULL.getCode());// 已满
                locationEntity.setUseStatus(LocationUseStatus.FULL.getCode());
            }

            locationEntity.setMaxNum(maxNum);
            locationMapper.updateById(locationEntity);

            // 计算 冻结 或者可用
            if (entity.getFree() != null) {
                log.info("可用库存不为空，计算冻结库存:{}", entity);
                entity.setFrozen(entity.getTotal() - entity.getFree());
            } else {
                log.info("冻结库存不为空，计算可用库存:{}", entity);
                entity.setFree(entity.getTotal() - entity.getFrozen());
            }
            log.info("更新库存信息:{}", entity);
            return super.saveOrUpdate(entity);
        } else {
            locationEntity.setUseStatus(LocationUseStatus.FREE.getCode()); // 库存已空
            locationEntity.setFrozen(LocationFrozen.NORMAL.getCode()); // 冻结状态改成正常
            locationEntity.setMaxNum(0); // 清空最大个数
            locationMapper.updateById(locationEntity);
            // 删除空库存
            return super.removeById(entity.getId());
        }
    }
}

